﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Windows.Forms;
using Assist;
using Autodesk.Revit.DB;
using YArchitech.Revit;

namespace YJKRevitFamilyDataBase
{
	internal class MySqlTypeTable : ITypeTable
	{
		public MySqlTypeTable(FamilyLibDatabase db)
		{
			this.mDatabase = db;
		}

		public bool Add(DataTable typeTable, DbFamily family, DbTransaction tr)
		{
			if (typeTable.Columns.Contains("TypeId"))
			{
				typeTable.Columns.Remove("TypeId");
			}
			string str = string.Format("insert into `{0}` (`{1}`", family.Guid.ToString(), typeTable.Columns[0].ColumnName);
			for (int i = 1; i < typeTable.Columns.Count; i++)
			{
				str = str + ",`" + typeTable.Columns[i].ColumnName + "`";
			}
			str += ") values (";
			for (int j = 0; j < typeTable.Rows.Count; j++)
			{
				if (typeTable.Rows[j]["规格名"].ToString().Trim() == "")
				{
					MessageBox.Show(family.Name + "族，第" + (j + 1).ToString() + "条记录规格名为空,添加失败。", "族库管理");
				}
				else
				{
					string text = str + "'" + typeTable.Rows[j][0].ToString() + "'";
					for (int k = 1; k < typeTable.Columns.Count; k++)
					{
						text = text + ",'" + typeTable.Rows[j][k].ToString() + "'";
					}
					text += ")";
					try
					{
						this.mDatabase.ExecuteCommand(text, tr);
					}
					catch
					{
						MessageBox.Show(family.Name + "族，第" + (j + 1).ToString() + "条记录添加失败，请检查规格名是否重名。", "族库管理");
					}
				}
			}
			typeTable.Rows.Clear();
			return true;
		}

		public void Update(DataTable typeTable, DbFamily family)
		{
			if (this.mDatabase.Connection.State == ConnectionState.Closed)
			{
				this.mDatabase.Connection.Open();
			}
			for (int i = 0; i < typeTable.Rows.Count; i++)
			{
				if (typeTable.Rows[i]["规格名"].ToString().Trim() == "")
				{
					MessageBox.Show("第" + (i + 1).ToString() + "条记录规格名为空,更新失败。", "族库管理");
				}
				else
				{
					string text = string.Format("UPDATE `{0}` SET `{1}`='{2}'", family.Guid.ToString(), typeTable.Columns[0].ColumnName, typeTable.Rows[i][0]);
					for (int j = 1; j < typeTable.Columns.Count; j++)
					{
						text += string.Format(",`{0}`='{1}'", typeTable.Columns[j].ColumnName, typeTable.Rows[i][j]);
					}
					text += string.Format(" WHERE `TypeId`='{0}'", typeTable.Rows[i]["TypeId"]);
					if (!this.mDatabase.ExecuteCommand(text))
					{
						MessageBox.Show("第" + i.ToString() + "条记录修改失败");
					}
				}
			}
			if (this.mDatabase.Connection.State == ConnectionState.Open)
			{
				this.mDatabase.Connection.Close();
			}
		}

		public DbFamilySymbol this[DbFamily family, string name]
		{
			get
			{
				DbFamilySymbol dbFamilySymbol = new DbFamilySymbol(family, name);
				dbFamilySymbol.SetDatabase(this.mDatabase);
				if (this.mDatabase.Connection.State == ConnectionState.Closed)
				{
					this.mDatabase.Connection.Open();
				}
				DataTable dataTable = this.mDatabase.ExecQuery(string.Format("select * from `{0}` where `规格名`='{1}'", family.Guid.ToString(), name.Trim()));
				if (this.mDatabase.Connection.State == ConnectionState.Open)
				{
					this.mDatabase.Connection.Close();
				}
				if (dataTable != null && dataTable.Rows.Count > 0)
				{
					dataTable.Columns.Remove("规格名");
					dataTable.Columns.Remove("TypeId");
					IFamilyParamTable familyParamTable = new SqliteFamilyParamTable(this.mDatabase);
					for (int i = 0; i < dataTable.Columns.Count; i++)
					{
						string columnName = dataTable.Columns[i].ColumnName;
						DbParamDefinition dbParamDefinition = familyParamTable[family, columnName];
						if (dbParamDefinition != null && dbParamDefinition.ParamDefinitionType != ParamDefinitionType.InstanceParam)
						{
							DbParameter item = new DbParameter(dbParamDefinition, dataTable.Rows[0][i]);
							dbFamilySymbol.Params.Add(item);
						}
					}
				}
				return dbFamilySymbol;
			}
		}

		DataTable ITypeTable.SelectTypes(string SQL)
		{
			throw new NotImplementedException();
		}

		public void AddColumns(DbFamily family, List<DbParamDefinition> paramDefs, DbTransaction tr)
		{
			for (int i = 0; i < paramDefs.Count; i++)
			{
				if (paramDefs[i].ParamDefinitionType != ParamDefinitionType.InstanceParam)
				{
					try
					{
						string typeStringFromStorageType = this.getTypeStringFromStorageType(paramDefs[i].StorageType);
						if (this.mDatabase.Connection.State == ConnectionState.Closed)
						{
							this.mDatabase.Connection.Open();
						}
						this.mDatabase.ExecuteCommand(string.Concat(new string[]
						{
							"alter table `",
							family.Guid.ToString(),
							"` add ",
							paramDefs[i].Name,
							" ",
							typeStringFromStorageType
						}), tr);
					}
					catch
					{
					}
				}
			}
		}

		private string getTypeStringFromStorageType(StorageType storageType)
		{
			string result = "varchar(200)";
            if (storageType == null || (int)storageType == 3 || (int)storageType == 4)
			{
				result = "varchar(200)";
			}
            else if ((int)storageType == 1)
			{
				result = "INT";
			}
            else if ((int)storageType == 2)
			{
				result = "DOUBLE";
			}
			return result;
		}

		private string getTypeStringFromType(Type type)
		{
			string result = "varchar(200)";
			if (type == typeof(string))
			{
				result = "varchar(200)";
			}
			else if (type == typeof(int) || type == typeof(long))
			{
				result = "INT";
			}
			else if (type == typeof(double))
			{
				result = "DOUBLE";
			}
			else if (type == null)
			{
				result = "DBNull";
			}
			return result;
		}

		public bool Create(DbFamily family, DbTransaction tr)
		{
			bool result;
			try
			{
				string text = string.Format("create table `{0}` (`TypeId` INT NOT NULL AUTO_INCREMENT,`规格名` varchar(200) NOT NULL", family.Guid.ToString());
				for (int i = 0; i < family.ParamDefinitionList.Count; i++)
				{
					string typeStringFromStorageType = this.getTypeStringFromStorageType(family.ParamDefinitionList[i].StorageType);
					if (family.ParamDefinitionList[i].ParamDefinitionType == ParamDefinitionType.CustomParam || family.ParamDefinitionList[i].ParamDefinitionType == ParamDefinitionType.TypeParam)
					{
						text += string.Format(",`{0}` {1}", family.ParamDefinitionList[i].Name.Trim(), typeStringFromStorageType);
					}
				}
				text += ",KEY `Id` (`TypeId`),CONSTRAINT `uk_name` unique (`规格名`));";
				if (this.mDatabase.ExecuteCommand(text, tr))
				{
					result = true;
				}
				else
				{
					result = false;
				}
			}
			catch (Exception ex)
			{
				throw ex;
			}
			return result;
		}

		public bool Create(DbFamily family, DataTable dt, DbTransaction tr)
		{
			bool result;
			try
			{
				string text = string.Format("create table `{0}` (`{1}` INT NOT NULL AUTO_INCREMENT", family.Guid.ToString(), dt.Columns[0].ColumnName.Trim());
				for (int i = 1; i < dt.Columns.Count; i++)
				{
					string typeStringFromType = this.getTypeStringFromType(dt.Columns[i].DataType);
					text += string.Format(",`{0}` {1}", dt.Columns[i].ColumnName.Trim(), typeStringFromType);
				}
				text += ",KEY `Id` (`TypeId`),CONSTRAINT `uk_name` unique (`规格名`));";
				if (this.mDatabase.ExecuteCommand(text, tr))
				{
					result = true;
				}
				else
				{
					result = false;
				}
			}
			catch (Exception ex)
			{
				throw ex;
			}
			return result;
		}

		public bool Drop(DbFamily family, DbTransaction tr)
		{
			bool result;
			try
			{
				if (this.mDatabase.ExecuteCommand(string.Format("DROP TABLE `{0}`", family.Guid.ToString()), tr))
				{
					result = true;
				}
				else
				{
					result = false;
				}
			}
			catch (Exception ex)
			{
				throw ex;
			}
			return result;
		}

		public DataTable DataTable(DbFamily family)
		{
			List<DbParamDefinition> list = new MySqlFamilyParamTable(this.mDatabase)[family];
			list.Sort(new ParamDefinitionComp());
			string text = "`TypeId`,`规格名`";
			for (int i = 0; i < list.Count; i++)
			{
				if (list[i].ParamDefinitionType != ParamDefinitionType.InstanceParam)
				{
					text = text + ",`" + list[i].Name + "`";
				}
			}
			if (this.mDatabase.Connection.State == ConnectionState.Closed)
			{
				this.mDatabase.Connection.Open();
			}
			DataTable result = this.mDatabase.ExecQuery(string.Concat(new string[]
			{
				"select ",
				text,
				" from `",
				family.Guid.ToString(),
				"`"
			}));
			if (this.mDatabase.Connection.State == ConnectionState.Open)
			{
				this.mDatabase.Connection.Close();
			}
			return result;
		}

		public List<string> this[DbFamily family]
		{
			get
			{
				List<string> list = new List<string>();
				DataTable dataTable = this.DataTable(family);
				if (dataTable != null)
				{
					for (int i = 0; i < dataTable.Rows.Count; i++)
					{
						list.Add(dataTable.Rows[i]["规格名"].ToString());
					}
				}
				return list;
			}
		}

		public bool Remove(int typeId, DbFamily family)
		{
			if (this.mDatabase.Connection.State == ConnectionState.Closed)
			{
				this.mDatabase.Connection.Open();
			}
			string commandStr = string.Concat(new object[]
			{
				"delete from `",
				family.Guid.ToString(),
				"` where TypeId='",
				typeId,
				"'"
			});
			if (this.mDatabase.ExecuteCommand(commandStr))
			{
				if (this.mDatabase.Connection.State == ConnectionState.Open)
				{
					this.mDatabase.Connection.Close();
				}
				return true;
			}
			if (this.mDatabase.Connection.State == ConnectionState.Open)
			{
				this.mDatabase.Connection.Close();
			}
			return false;
		}

		private FamilySymbol FindSymbol(Family family, string symbolName)
		{
			FamilySymbol result = null;
			foreach (FamilySymbol familySymbol in family.GetSymbols())
			{
				if (familySymbol.Name == symbolName || familySymbol.Name == symbolName.ToUpper() || familySymbol.Name == symbolName.ToLower())
				{
					result = familySymbol;
					break;
				}
			}
			return result;
		}

		public FamilySymbol CreateFamilySymbol(DbFamily dbFamily, string name, Autodesk.Revit.DB.Document doc)
		{
			if (this.mDatabase.Connection.State == ConnectionState.Closed)
			{
				this.mDatabase.Connection.Open();
			}
			bool flag = false;
			Document document = null;
			Watch watch = new Watch();
			watch.Start("查找或加载族");
			Family family = dbFamily.Load(doc);
			watch.Stop();
			watch.Start("查找规格");
			FamilySymbol familySymbol = this.FindSymbol(family, name);
			watch.Stop();
			if (familySymbol == null)
			{
				watch.Start("创建规格");
				this.CreateNewType(dbFamily, name, doc, ref flag, ref document, family);
				watch.Stop();
			}
			else
			{
				watch.Start("对比创建GUID及已有参数");
				this.UpdateType(dbFamily, name, doc, ref flag, ref document, family, familySymbol);
				watch.Stop();
			}
			if (flag)
			{
				watch.Start("重新加载族");
				family = document.LoadFamily(doc, new FamilyOptions());
				familySymbol = this.FindSymbol(family, name);
				watch.Stop();
			}
			if (document != null)
			{
				document.Close(false);
				document.Dispose();
			}
			if (this.mDatabase.Connection.State == ConnectionState.Open)
			{
				this.mDatabase.Connection.Close();
			}
			return familySymbol;
		}

		private void UpdateType(DbFamily dbFamily, string name, Autodesk.Revit.DB.Document doc, ref bool reLoad, ref Document familyDoc, Family family, FamilySymbol fs)
		{
			Parameter parameter = fs.GetParameter("GUID");
			if (parameter == null || parameter.AsString() == "")
			{
				if (familyDoc == null)
				{
					familyDoc = doc.EditFamily(family);
				}
				FamilyManager familyManager = familyDoc.FamilyManager;
				Transaction transaction = new Transaction(familyDoc, "CreateGUID");
				transaction.Start();
				try
				{
					if (familyDoc.IsFamilyDocument)
					{
						reLoad = true;
						foreach (object obj in familyManager.Types)
						{
							FamilyType familyType = (FamilyType)obj;
							if (familyType.Name == fs.Name)
							{
								familyManager.CurrentType = familyType;
								break;
							}
						}
						if (familyManager.get_Parameter("GUID") == null)
						{
							FamilyParameter familyParameter = familyManager.AddParameter("GUID", BuiltInParameterGroup.PG_TEXT, (Autodesk.Revit.DB.ParameterType)1, false);
							familyManager.Set(familyParameter, dbFamily.Guid.ToString());
							transaction.Commit();
						}
					}
				}
				catch
				{
					transaction.RollBack();
				}
			}
			if (this.mDatabase.Connection.State == ConnectionState.Closed)
			{
				this.mDatabase.Connection.Open();
			}
			DataTable dataTable = this.mDatabase.ExecQuery(string.Concat(new string[]
			{
				"select * from ",
				dbFamily.Guid.ToString(),
				"where 规格名=\"",
				name.Trim(),
				"\""
			}));
			if (this.mDatabase.Connection.State == ConnectionState.Open)
			{
				this.mDatabase.Connection.Close();
			}
			if (dataTable != null && dataTable.Rows.Count > 0)
			{
				dataTable.Columns.Remove("规格名");
				dataTable.Columns.Remove("TypeId");
				IFamilyParamTable familyParamTable = new SqliteFamilyParamTable(this.mDatabase);
				for (int i = 0; i < dataTable.Columns.Count; i++)
				{
					string columnName = dataTable.Columns[i].ColumnName;
					DbParamDefinition dbParamDefinition = familyParamTable[dbFamily, columnName];
					if (dbParamDefinition != null && dbParamDefinition.ParamDefinitionType == ParamDefinitionType.CustomParam && dataTable.Rows[0][i] != null && Convert.ToString(dataTable.Rows[0][i]) != "")
					{
						DbParameter dbParameter = new DbParameter(dbParamDefinition, dataTable.Rows[0][i]);
						if (dbParameter.ParamDefinition.ParamDefinitionType != ParamDefinitionType.TypeParam && dbParameter.ParamDefinition.ParamDefinitionType == ParamDefinitionType.CustomParam && fs.GetParameter(dbParameter.ParamDefinition.Name) == null)
						{
							if (familyDoc == null)
							{
								familyDoc = doc.EditFamily(family);
							}
							FamilyManager familyManager2 = familyDoc.FamilyManager;
							Transaction transaction2 = new Transaction(familyDoc, "CreateCustomParam");
							transaction2.Start();
							try
							{
								reLoad = true;
								FamilyParameter familyParameter2 = familyManager2.AddParameter(dbParameter.ParamDefinition.Name, BuiltInParameterGroup.PG_TEXT, (Autodesk.Revit.DB.ParameterType)1, false);
                                switch ((int)familyParameter2.StorageType)
								{
								case 1:
									familyManager2.Set(familyParameter2, Convert.ToInt32(dbParameter.Value));
									break;
								case 2:
									familyManager2.Set(familyParameter2, AssistFunc.mmToFeet(Convert.ToDouble(dbParameter.Value)));
									break;
								case 3:
									familyManager2.Set(familyParameter2, Convert.ToString(dbParameter.Value));
									break;
								case 4:
								{
									object value = dbParameter.Value;
									break;
								}
								}
								transaction2.Commit();
							}
							catch
							{
								transaction2.RollBack();
							}
						}
					}
				}
			}
		}

		private void CreateNewType(DbFamily dbFamily, string name, Autodesk.Revit.DB.Document doc, ref bool reLoad, ref Document familyDoc, Family family)
		{
			familyDoc = doc.EditFamily(family);
			if (familyDoc != null && familyDoc.IsFamilyDocument)
			{
				FamilyManager familyManager = familyDoc.FamilyManager;
				Transaction transaction = new Transaction(familyDoc, "CreateTypeTransaction");
				transaction.Start();
				try
				{
					SubTransaction subTransaction = new SubTransaction(familyDoc);
					subTransaction.Start();
					try
					{
						if (familyManager.get_Parameter("GUID") == null)
						{
							reLoad = true;
							FamilyParameter familyParameter = familyManager.AddParameter("GUID", BuiltInParameterGroup.PG_TEXT, (Autodesk.Revit.DB.ParameterType)1, false);
							familyManager.Set(familyParameter, dbFamily.Guid.ToString());
						}
						subTransaction.Commit();
					}
					catch
					{
						subTransaction.RollBack();
					}
					familyManager.NewType(name);
					if (this.mDatabase.Connection.State == ConnectionState.Closed)
					{
						this.mDatabase.Connection.Open();
					}
					DataTable dataTable = this.mDatabase.ExecQuery(string.Concat(new string[]
					{
						"select * from ",
						dbFamily.Guid.ToString(),
						"where 规格名=\"",
						name.Trim(),
						"\""
					}));
					if (this.mDatabase.Connection.State == ConnectionState.Open)
					{
						this.mDatabase.Connection.Close();
					}
					if (dataTable != null && dataTable.Rows.Count > 0)
					{
						dataTable.Columns.Remove("规格名");
						dataTable.Columns.Remove("TypeId");
						IFamilyParamTable familyParamTable = new SqliteFamilyParamTable(this.mDatabase);
						for (int i = 0; i < dataTable.Columns.Count; i++)
						{
							string columnName = dataTable.Columns[i].ColumnName;
							DbParamDefinition dbParamDefinition = familyParamTable[dbFamily, columnName];
							if (dbParamDefinition != null && dbParamDefinition.ParamDefinitionType != ParamDefinitionType.InstanceParam && dataTable.Rows[0][i] != null && Convert.ToString(dataTable.Rows[0][i]) != "")
							{
								DbParameter dbParameter = new DbParameter(dbParamDefinition, dataTable.Rows[0][i]);
								if (dbParameter.ParamDefinition.ParamDefinitionType == ParamDefinitionType.TypeParam)
								{
									SubTransaction subTransaction2 = new SubTransaction(familyDoc);
									subTransaction2.Start();
									try
									{
										FamilyParameter familyParameter2 = familyManager.get_Parameter(dbParameter.ParamDefinition.Name);
										if (familyParameter2 != null && !familyParameter2.IsReadOnly)
										{
                                            switch ((int)familyParameter2.StorageType)
											{
											case 1:
												familyManager.Set(familyParameter2, Convert.ToInt32(dbParameter.Value));
												break;
											case 2:
												familyManager.Set(familyParameter2, Convert.ToDouble(dbParameter.Value) / Convert.ToDouble(UnitConvertC.ImperialDutRatio(dbParameter.ParamDefinition.DisplayUnitType)));
												break;
											case 3:
												familyManager.Set(familyParameter2, Convert.ToString(dbParameter.Value));
												break;
											case 4:
											{
												object value = dbParameter.Value;
												break;
											}
											}
										}
										subTransaction2.Commit();
										goto IL_3DD;
									}
									catch
									{
										subTransaction2.RollBack();
										goto IL_3DD;
									}
								}
								if (dbParameter.ParamDefinition.ParamDefinitionType == ParamDefinitionType.CustomParam)
								{
									SubTransaction subTransaction3 = new SubTransaction(familyDoc);
									subTransaction3.Start();
									try
									{
										FamilyParameter familyParameter3 = familyManager.AddParameter(dbParameter.ParamDefinition.Name, BuiltInParameterGroup.PG_TEXT, (Autodesk.Revit.DB.ParameterType)1, false);
										if (familyParameter3 != null && !familyParameter3.IsReadOnly)
										{
                                            switch ((int)familyParameter3.StorageType)
											{
											case 1:
												familyManager.Set(familyParameter3, Convert.ToInt32(dbParameter.Value));
												break;
											case 2:
												familyManager.Set(familyParameter3, AssistFunc.mmToFeet(Convert.ToDouble(dbParameter.Value)));
												break;
											case 3:
												familyManager.Set(familyParameter3, Convert.ToString(dbParameter.Value));
												break;
											case 4:
											{
												object value2 = dbParameter.Value;
												break;
											}
											}
										}
										subTransaction3.Commit();
									}
									catch
									{
										subTransaction3.RollBack();
									}
								}
							}
							IL_3DD:;
						}
					}
					transaction.Commit();
				}
				catch (Exception ex)
				{
					transaction.RollBack();
					throw ex;
				}
				finally
				{
					transaction.Dispose();
				}
			}
		}

		public FamilySymbol CreateFamilySymbol(DbFamily dbFamily, string name, Autodesk.Revit.DB.Document doc, ref int host)
		{
			Family family = dbFamily.Load(doc);
			Parameter parameter = family.get_Parameter(BuiltInParameter.FAMILY_HOSTING_BEHAVIOR);
			if (parameter != null)
			{
				host = parameter.AsInteger();
			}
			bool flag = false;
			Document document = null;
			FamilySymbol familySymbol = this.FindSymbol(family, name);
			if (familySymbol == null)
			{
				this.CreateNewType(dbFamily, name, doc, ref flag, ref document, family);
			}
			else
			{
				this.UpdateType(dbFamily, name, doc, ref flag, ref document, family, familySymbol);
			}
			if (flag)
			{
				family = document.LoadFamily(doc, new FamilyOptions());
				familySymbol = this.FindSymbol(family, name);
			}
			if (document != null)
			{
				document.Close(false);
				document.Dispose();
			}
			return familySymbol;
		}

		private bool CompareParameter(Parameter param, DbParameter dbParam)
		{
			bool result = false;
            switch ((int)param.StorageType)
			{
			case 0:
				result = true;
				break;
			case 1:
			{
				int num = param.AsInteger();
				int num2 = Convert.ToInt32(dbParam.Value);
				if (num == num2)
				{
					result = true;
				}
				break;
			}
			case 2:
			{
				double num3 = param.AsDouble();
				double num4 = AssistFunc.mmToFeet(Convert.ToDouble(dbParam.Value));
				if (num3 == num4)
				{
					result = true;
				}
				break;
			}
			case 3:
			{
				string a = param.AsString();
				string a2 = param.AsValueString();
				string b = Convert.ToString(dbParam.Value);
				if (a == b || a2 == b)
				{
					result = true;
				}
				break;
			}
			case 4:
			{
				int integerValue = param.AsElementId().IntegerValue;
				int num5 = Convert.ToInt32(dbParam.Value);
				if (integerValue == num5)
				{
					result = true;
				}
				break;
			}
			}
			return result;
		}

		private FamilyLibDatabase mDatabase;
	}
}
